#ifndef _WANGXUAN_FILE_MANAGER_H_
#define _WANGXUAN_FILE_MANAGER_H_

#include <errno.h>
#include <sys/mman.h>
#include <map>
#include "data_struct.h"
#include "lru_list.h"
#include "dirty_list.h"


class IndexFilePage;
class IndexFileHeader;

class IndexFile
{
public:
	IndexFile(const char* path,const char* prefix,int seq);
	~IndexFile();
	friend class IndexManager;
public:
	int getPage(unsigned int offset,IndexFilePage** page);
	int getHeadPage(IndexFileHeader** page);

	int freePage(unsigned int offset);
	unsigned int getPageCount();

	int remap();
	
	int getSeq();
	int stat();
private:
	int init();
private:
	int fd;
	int seq;
	char theFile[200];

	map<int,Page*> pagesMap;
};

class Page
{
	friend class LRUList;
	friend class DirtyList;
public:
	Page(void* addr);
	virtual ~Page();
public:
	int pollute();
	int flush();
protected:
	char* mappedAddr;
	LRULISTPOS lruPos;
	DIRTYLISTPOS dirtyPos;
	unsigned int lastAccessTime;
	bool isDirty;
private:
};

class IndexFileHeader:public Page
{
	friend class IndexFile;
	friend class IndexManager;
public:
	IndexFileHeader(void* addr);
	virtual ~IndexFileHeader(){};

	string dump();
private:
	FileHeader* fh;
};


class IndexFilePage:public Page
{
	friend class IndexFile;
	friend class IndexManager;
public:
	enum PAGETTYPE  {EMPTY = 0X00,LEAF = 0X40,INNER=0X80};
	IndexFilePage(void* addr);
	virtual ~IndexFilePage(){};

	int insert(const void* key,uint64_t msgId);
	int del(const void* key,uint64_t msgId);

	//0 free,1 leaf-node,2 inner-node
	int getType();
	void setType(PAGETTYPE type);
	
	string dump(const char* keyConfig,bool detail=true);
private:
	NODE* node;
	uint64_t offset;
};


//inline func define 

inline int IndexFile::getSeq()
{
	return seq;
}

inline unsigned int IndexFile::getPageCount(){
	return pagesMap.size();
}

inline int IndexFile::stat()
{
	if(fd <= 0 ){
		return -1;
	}

	return 0;
}

inline int Page::pollute(){

	DirtyList::instance()->update(this);
	isDirty = true;
	
	return 0;
}

inline int IndexFilePage::getType(){
	return node->flag; 
}

inline void IndexFilePage::setType(PAGETTYPE type){
	node->flag = type;
}

#endif
